using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class VirtualJoyStick : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler
{
    public RectTransform background;

    public RectTransform joystick;

    public float maxDragRadius = 20.0f;

    public float minValidDragRadius = 5.0f;

    private Vector2 spawnPosition;

    private float prevDragAngle = 0.0f;

    private float prevDragDistance = 0.0f;

    private bool wasMoving => prevDragDistance >= minValidDragRadius;

    public event Action<float, float> onMove;

    public event Action onStop;

    // Start is called before the first frame update
    void Start()
    {
        background.gameObject.SetActive(false);
        joystick.gameObject.SetActive(false);
    }

    // Update is called once per frame
    void Update()
    {

    }

    public void OnPointerDown(PointerEventData eventData)
    {
        spawnPosition = eventData.position;

        background.gameObject.SetActive(true);
        background.position = spawnPosition;

        joystick.gameObject.SetActive(true);
        joystick.position = spawnPosition;

        prevDragAngle = 0;
        prevDragDistance = 0.0f;
    }
    public void OnPointerUp(PointerEventData eventData)
    {
        background.gameObject.SetActive(false);
        joystick.gameObject.SetActive(false);

        if (wasMoving)
        {
            onStop?.Invoke();

            prevDragAngle = 0;
            prevDragDistance = 0;
        }
    }

    public void OnDrag(PointerEventData eventData)
    {
        Vector2 distance = eventData.position - spawnPosition;
        float validDistance = Mathf.Min(distance.magnitude, maxDragRadius);
        float angleInRad = Mathf.Atan2(distance.y, distance.x);
        float angleInDeg = angleInRad * Mathf.Rad2Deg;

        joystick.position = spawnPosition + new Vector2(Mathf.Cos(angleInRad) * validDistance, Mathf.Sin(angleInRad) * validDistance);

        if (validDistance < minValidDragRadius)
        {
            if (wasMoving)
            {
                onStop?.Invoke();

                prevDragAngle = 0;
                prevDragDistance = 0;
            }
        }
        else
        {
            if(wasMoving)
            {
                bool moveChanged = false;
                if (Mathf.Abs(angleInDeg - prevDragAngle) >= 1.0f)
                {
                    prevDragAngle = angleInDeg;
                    moveChanged = true;
                }

                if (Mathf.Abs(validDistance - prevDragDistance) / (maxDragRadius - minValidDragRadius) >= 0.1f)
                {
                    prevDragDistance = validDistance;
                    moveChanged = true;
                }

                if(moveChanged)
                {
                    onMove?.Invoke(prevDragAngle, (prevDragDistance - minValidDragRadius)/(maxDragRadius - minValidDragRadius));
                }
            }
            else
            {
                prevDragAngle = angleInDeg;
                prevDragDistance = validDistance;
                onMove?.Invoke(prevDragAngle, (prevDragDistance - minValidDragRadius) / (maxDragRadius - minValidDragRadius));
            }
        }
    }


}
